package by.shade.parser;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.lang3.StringUtils;

import by.shade.news.Item;
import by.shade.news.News;

import com.sun.syndication.feed.synd.SyndContent;
import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.feed.synd.SyndPerson;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;

/**
 * Feed (RSS/Atom) parser.
 *
 * @author homyakov
 * @version $Id: FeedParser.java 5 2012-08-14 16:02:17Z vkhomyackov@gmail.com $
 */
public class FeedParser implements INewsParser {

    private static final Logger LOG = Logger.getLogger(FeedParser.class.getName());

    public News parse(String url) {
        try {
            SyndFeed feed = read(url);
            return feed2news(feed);
        } catch (Exception e) {
            LOG.log(Level.WARNING, "Cannot parse URL " + url, e);
        }
        return new News();
    }

    private static SyndFeed read(String url) throws IOException, MalformedURLException,
            FeedException {
        XmlReader reader = null;
        try {
            reader = new XmlReader(new URL(url));
            SyndFeed feed = new SyndFeedInput().build(reader);
            return feed;
        } finally {
            if (reader != null) {
                reader.close();
            }
        }
    }

    private static News feed2news(SyndFeed feed) {
        News news = new News();

        news.setAuthors(feedAuthors(feed));
        news.setTitle(feed.getTitle());
        // feed.getDescription()
        // feed.getPublishedDate()

        @SuppressWarnings("unchecked")
        List<SyndEntry> entries = feed.getEntries();
        for (SyndEntry entry : entries) {
            news.add(entry2item(entry));
        }

        return news;
    }

    private static String feedAuthors(SyndFeed feed) {
        // TODO cleanup nulls
        StringBuilder result = new StringBuilder();

        if (StringUtils.isNotEmpty(feed.getAuthor())) {
            result.append(feed.getAuthor());
        }

        @SuppressWarnings("unchecked")
        List<SyndPerson> authors = feed.getAuthors();
        if (authors != null) {
            for (SyndPerson author : authors) {
                if (result.length() > 0) {
                    result.append("; ");
                }
                result.append(author.getName()).append(' ').append(author.getEmail()).append(' ')
                        .append(author.getUri());
            }
        }

        return result.toString();
    }

    private static Item entry2item(SyndEntry entry) {
        Item item = new Item();
        item.setTitle(entry.getTitle());
        item.setAuthor(entry.getAuthor()); // TODO process getAuthors()
        item.setLink(entry.getLink()); // TODO getLinks()

        StringBuilder content = new StringBuilder();
        @SuppressWarnings("unchecked")
        List<SyndContent> contents = entry.getContents();
        for (SyndContent syndContent : contents) {
            content.append(syndContent.getType()).append(syndContent.getValue());
        }
        item.setContent(content.toString());

        SyndContent description = entry.getDescription();
        if (description != null) {
            item.setDescription(description.getValue());
        }

        item.setDate(entry.getPublishedDate());

        return item;
    }

}
